use std::collections::{HashMap};
use chrono::Local;
use crate::db::dao::im_group_dao::{group_inserts, group_total, group_update, group_updates, group_user_insert_or_updates, group_user_query_by_group_id, query_group_by_group_code, query_groups_by_group_codes};
use crate::db::dao::im_session_dao::{session_get_by_group_code_and_user_id, session_update, session_updates};
use crate::db::db::Db;
use crate::db::db_transaction::transaction;
use crate::db::pojo::pojo::{ImGroup, ImGroupStatus, ImSession};

pub struct ImGroupService;

impl ImGroupService {

    pub fn save_groups(&self, users: &mut Vec<ImGroup>) {
        let db = Db::open();
        transaction(db.clone(), move |db: Db| {
            self.save_groups_business(db, users)
        });
    }

    pub fn total(&self)->usize {
        let db = Db::open();
        let total = transaction(db.clone(), move |db: Db| {
            group_total(db)
        });
        total
    }

    pub fn query_group(&self, group_code: &str)->Option<ImGroup> {
        let db = Db::open();
        let group = query_group_by_group_code(db.clone(), group_code);
        match group {
            None => {None}
            Some(mut group) => {
                let group_users = group_user_query_by_group_id(db.clone(), group.id.unwrap());
                group.group_users = Some(group_users);
                Some(group)
            }
        }
    }

    pub fn send_success(mut group: &mut ImGroup, session_server_id: String) {
        let db = Db::open();
        
        group.server_id = Some(group.code.clone());
        group.update_time = Local::now();
        group.status = ImGroupStatus::Enable;
        
        group_update(db.clone(), &mut group);

        let session = session_get_by_group_code_and_user_id(db.clone(), &group.code, &group.current_user_id);
        if let Some(mut session) = session {
            session.server_id = Some(session_server_id);
            session.update_time = Local::now();
            session_update(db.clone(), &mut session);
        }
    }

    fn save_groups_business(&self, db: Db, groups: &mut Vec<ImGroup>) {
        let group_codes = groups.iter().map(|group| {group.code.clone()}).collect::<Vec<String>>();
        log::info!("db group codes: {:?}", group_codes);
        let db_groups = query_groups_by_group_codes(db.clone(), group_codes);
        log::info!("db groups: {:?}", db_groups);
        let db_groups = db_groups.into_iter().map(|group| {(group.code.clone(), group)}).collect::<HashMap<_, _>>();

        let mut insert_groups= Vec::new();
        let mut update_groups = Vec::new();
        let mut update_group_users = Vec::new();
        let mut update_sessions = Vec::new();

        for group in groups.iter_mut() {
            let code = &group.code;
            let db_group = db_groups.get(code);
            match db_group {
                None => {
                    insert_groups.push(group);
                }
                Some(db_group) => {
                    group.id = db_group.id.clone();
                    let group_option = (&group.group_users).clone();
                    if let Some(group_users) = group_option {
                        for mut group_user in group_users.into_iter() {
                            group_user.id = Some(db_group.id.clone().unwrap());
                            update_group_users.push(group_user);
                        }
                    }

                    let name = group.name.clone();
                    if let Some(name) = name { // 群信息变更了
                        let code = group.code.clone();
                        let current_user_id = group.current_user_id.clone();
                        update_groups.push(group);

                        let db_session = session_get_by_group_code_and_user_id(db.clone(), &code, &current_user_id);
                        if let Some(mut db_session) = db_session {
                            db_session.name = name.clone();
                            db_session.update_time = Local::now();

                            update_sessions.push(db_session);
                        }
                    }
                }
            }
        }

        group_inserts(db.clone(), &mut insert_groups);
        group_updates(db.clone(), &mut update_groups);
        group_user_insert_or_updates(db.clone(), &mut update_group_users);

        let mut update_session_list = update_sessions.iter_mut().map(|session| session).collect::<Vec<&mut ImSession>>();
        session_updates(db.clone(), &mut update_session_list);
    }
}
